package handler

import (
    "fcs-api/src/app/business"
    "fcs-api/src/app/model"
    "fcs-api/src/app/service/ksvc"
    "fcs-api/src/app/service/pingsource"
    "fcs-api/src/app/utils"
    "fmt"
    "net/http"
    "strconv"
    "strings"

    "bytes"

    "encoding/json"

    i18n "git.inspur.com/x/common/i18n"
    "github.com/emicklei/go-restful"
    "github.com/robfig/cron"
    "k8s.io/apimachinery/pkg/util/rand"
)

func (api *APIHandler) handleCreateTrigger(request *restful.Request, response *restful.Response) {
    logger.Debug("handleCreateTrigger start.")

    fcClient, err := GetFcClient(api)
    if err != nil {
        _ = logger.Error("handleCreateTrigger get cmanagerconfig error %v", err)
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
        return
    }
    trigger, err := ReadAndValidateTrigger(request)
    if err != nil {
        _ = logger.Error("handleCreateTrigger ReadAndValidateTrigger error %v", err)
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
        return
    }
    logger.Debug("handleCreateTrigger trigger : %v", trigger)
    from := request.QueryParameter("from")

    if trigger.Type == "timer" {
        if _, err := cron.ParseStandard(trigger.Config); err != nil {
            _ = logger.Error("handleCreateTrigger cron error %v", err)
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.crontab")))
            return
        }
    }

    has, err := model.CheckTriggerExist(trigger.Creator, trigger.GroupId, trigger.FuncId, trigger.Name)
    if err != nil {
        _ = logger.Error("handleCreateTrigger GetTrigger error %v", err)
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
        return
    }
    if has {
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create_dup")))
        return
    }

    // custom-container 只支持 HTTP 触发器
    functionInfo := getFunctionById(trigger.FuncId).(*model.FuncInfo)
    if functionInfo == nil {
        _ = logger.Error("handleCreateTrigger getFunctionById error %v", err)
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
        return
    }
    if functionInfo.Runtime != model.CustomContainer && trigger.Type == "http" {
        _ = logger.Error("handleCreateTrigger functionInfo.Runtime != model.CustomContainer error %v", err)
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create_http_no")))
        return
    }
    if functionInfo.Runtime == model.CustomContainer && trigger.Type != "http" {
        _ = logger.Error("handleCreateTrigger functionInfo.Runtime != model.CustomContainer error %v", err)
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create_http_yes")))
        return
    }

    switch trigger.Type {
    case "timer":
        // 定时触发器
        namespace := ksvc.GetTriggerNs(trigger)
        if trigger.IsEnable == 1 { //定时器开启
            err = pingsource.CreatePingsource(fcClient, namespace, trigger)
            if err != nil {
                handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
                return
            }
        }
    case "oss":
        // 对象存储触发器
        ossN := &model.OssNotification{}
        _ = json.Unmarshal([]byte(trigger.Config), ossN)
        ruleId := fmt.Sprintf("%s.%s.%s", trigger.GroupName, trigger.FuncName, trigger.Name)
        ossN.Id = ruleId
        ossN.Topic = "irn:fcs:" + trigger.RegionCode + ":" + trigger.Creator + ":" + "exchange.fcs"
        logger.Debug("handleCreateTrigger ossN : %v", ossN)
        ossApiHost := model.Base.OssAdminHost
        if model.Base.OssUserHost != "" {
            ossApiHost = model.Base.OssUserHost
        }
        token := request.HeaderParameter("Authorization")
        err := createOssNotification(ossApiHost, token, ossN)
        if err != nil {
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
            return
        }
        n, err := json.Marshal(ossN)
        if err != nil {
            _ = logger.Error("json.Marshal err : ", err)
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
            return
        }
        trigger.Config = string(n)
    case "apig":
        // API 网关触发器
        apigC := &model.ApigConfig{}
        _ = json.Unmarshal([]byte(trigger.Config), apigC)
        apigC = assembleApigConfig(trigger, apigC)
        logger.Debug("handleCreateTrigger apigC : %v", apigC)
        token := request.HeaderParameter("Authorization")
        if from != "apig" {
            apiInfo, err := createApig(model.Base.ApigHost, token, apigC)
            if err != nil {
                handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
                return
            }
            err = publishApig(model.Base.ApigHost, token, apigC.GroupId, apiInfo.Id, apigC.IsRelease)
            if err != nil {
                //回滚删除创建的api
                _ = deleteApig(model.Base.ApigHost, token, apiInfo.Id)
                handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
                return
            }
            apigC.Id = apiInfo.Id
        }
        invokeUrl, err := getInvokeUrl(model.Base.ApigHost, token, apigC)
        if err != nil {
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
            return
        }
        apiInfoStr, _ := json.Marshal(apigC)
        trigger.Config = getNewConfig(string(apiInfoStr), "invokeUrl", invokeUrl)
        logger.Debug("handleCreateTrigger trigger.Config : %v", trigger.Config)
    case "http":
        // HTTP 触发器
        // 1. 校验同一个函数的同一个版本/别名只能有一个 HTTP 触发器
        exist, err := model.CheckHttpTriggerExist(trigger)
        if err != nil {
            _ = logger.Error("handleCreateTrigger CheckHttpTriggerExist error %v", err)
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
            return
        }
        if exist {
            handleInternalError(response, model.InternalServerError(model.TriggerError,
                "创建触发器失败，同一函数的同一版本/别名只能创建一个 HTTP 触发器"))
            return
        }
        // 2. 创建 HTTP 触发器对应的 Service 和 KongPlugin
        err = business.CreateHttpTriggerKongPlugin(fcClient, trigger)
        if err != nil {
            _ = logger.Error("handleCreateTrigger CreateHttpTriggerKongPlugin error %v", err)
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
            return
        }
        err = business.CreateHttpTriggerService(fcClient, trigger)
        if err != nil {
            _ = logger.Error("handleCreateTrigger CreateHttpTriggerService error %v", err)
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
            return
        }
        // 3. 创建并获取账号对应的唯一 Ingress default-<accountId>，并创建路由规则
        err = business.CreateHttpTriggerIngress(fcClient, trigger)
        if err != nil {
            _ = logger.Error("handleCreateTrigger CreateHttpTriggerIngress error %v", err)
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
            return
        }
    default:
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.type_create")))
        return
    }

    //更新数据库
    trigger, err = model.CreateTrigger(trigger)
    if err != nil {
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.create")))
        return
    }

    _ = response.WriteHeaderAndEntity(http.StatusOK, trigger)
}

func (api *APIHandler) handleGetTriggerList(request *restful.Request, response *restful.Response) {
    logger.Debug("handleGetTriggerList start.")
    groupId := request.PathParameter("groupId")
    funcId := request.PathParameter("functionId")
    name := request.QueryParameter("name")
    tType := request.QueryParameter("type")
    pageNoStr := request.QueryParameter("pageNo")
    pageSizeStr := request.QueryParameter("pageSize")

    var err error
    pageNo, pageSize := 1, 1000000
    if pageNoStr != "" || pageSizeStr != "" {
        pageNo, err = strconv.Atoi(pageNoStr)
        if err != nil {
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.list_param")))
            return
        }
        pageSize, err = strconv.Atoi(pageSizeStr)
        if err != nil {
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.list_param")))
            return
        }
    }

    user := currentUser(request)
    if groupId == "0" {
        groupId = ""
    }
    if funcId == "0" {
        funcId = ""
    }

    triggerPage, err := model.GetTriggerList(groupId, funcId, user, name, tType, pageNo, pageSize)
    if err != nil {
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.list")))
        return
    }
    _ = response.WriteHeaderAndEntity(http.StatusOK, triggerPage)
}

func (api *APIHandler) handleGetTriggerDetail(request *restful.Request, response *restful.Response) {
    logger.Debug("handleGetTriggerDetail start.")
    triggerId := request.PathParameter("triggerId")
    trigger, err := model.GetTriggerById(triggerId)
    if err != nil {
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.detail")))
        return
    }
    if trigger.Id == "" {
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.detail")))
        return
    }
    _ = response.WriteHeaderAndEntity(http.StatusOK, trigger)
}

func (api *APIHandler) handleUpdateTrigger(request *restful.Request, response *restful.Response) {
    logger.Debug("handleUpdateTrigger start.")

    fcClient, err := GetFcClient(api)
    if err != nil {
        _ = logger.Error("handleUpdateTrigger get cmanagerconfig error %v", err)
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
        return
    }
    trigger, err := ReadAndValidateTrigger(request)
    if err != nil {
        _ = logger.Error("handleUpdateTrigger ReadAndValidateTrigger error %v", err)
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
        return
    }
    trigger.Id = request.PathParameter("triggerId")
    logger.Debug("handleUpdateTrigger ReadEntity : %v", trigger)
    namespace := ksvc.GetTriggerNs(trigger)

    switch trigger.Type {
    case "timer":
        // 定时触发器
        if _, err := cron.ParseStandard(trigger.Config); err != nil {
            _ = logger.Error("handleUpdateTrigger cron error %v", err)
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.crontab")))
            return
        }
        if trigger.IsEnable == 1 { //开启
            if err = pingsource.UpdatePingsource(fcClient, namespace, trigger); err != nil {
                if strings.Contains(err.Error(), "not found") {
                    if err = pingsource.CreatePingsource(fcClient, namespace, trigger); err != nil {
                        _ = logger.Error("handleUpdateTrigger CreatePingsource error %v", err)
                        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
                        return
                    }
                } else {
                    _ = logger.Error("handleUpdateTrigger UpdatePingsource error %v", err)
                    handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
                    return
                }
            }
        }
        if trigger.IsEnable == 0 { //关闭
            triggerName := trigger.FuncName + "-" + trigger.Name
            if err = pingsource.DeletePingsource(fcClient, namespace, triggerName); err != nil {
                if !strings.Contains(err.Error(), "not found") {
                    _ = logger.Error("handleUpdateTrigger DeletePingsource error %v", err)
                    handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
                    return
                }
            }
        }
    case "oss":
        // 对象存储触发器
        // 没有事件更新功能
        break
    case "apig":
        // API 网关触发器
        oldT, _ := model.GetTriggerById(trigger.Id)
        oldApigC := &model.ApigConfig{}
        _ = json.Unmarshal([]byte(oldT.Config), oldApigC)
        apigC := &model.ApigConfig{}
        _ = json.Unmarshal([]byte(trigger.Config), apigC)
        apigC = assembleApigConfig(trigger, apigC)
        apigC.Id = oldApigC.Id
        logger.Debug("handleUpdateTrigger apigC : %v", apigC)
        token := request.HeaderParameter("Authorization")
        apiInfo, err := updateApig(model.Base.ApigHost, token, apigC)
        if err != nil {
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
            return
        }
        if oldApigC.IsRelease != apigC.IsRelease {
            err = offlineApig(model.Base.ApigHost, token, apigC.Id, oldApigC.IsRelease)
            if err != nil {
                handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
                return
            }
            err = publishApig(model.Base.ApigHost, token, apigC.GroupId, apiInfo.Id, apigC.IsRelease)
            if err != nil {
                handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
                return
            }
        }
        invokeUrl, err := getInvokeUrl(model.Base.ApigHost, token, apigC)
        if err != nil {
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
            return
        }
        apiInfoStr, _ := json.Marshal(apigC)
        trigger.Config = getNewConfig(string(apiInfoStr), "invokeUrl", invokeUrl)
        logger.Debug("handleUpdateTrigger trigger.Config : %v", trigger.Config)
    case "http":
        // HTTP 触发器
        // 先获取数据库内已存在的触发器数据
        oldTriggerInfo, err := model.GetTriggerById(trigger.Id)
        if err != nil {
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
            return
        }
        // 再判断是否更新了触发版本/别名
        if oldTriggerInfo.TargetName == trigger.TargetName {
            // 1. 如果未更新触发版本/别名，则只有 Service 需要更新
            oldTriggerConfig, err := business.GetHttpTriggerConfig(oldTriggerInfo)
            if err != nil {
                handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
                return
            }
            newTriggerConfig, err := business.GetHttpTriggerConfig(trigger)
            if err != nil {
                handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
                return
            }
            // 触发器配置有变动，当前只有一个配置项
            if oldTriggerConfig.AuthType != newTriggerConfig.AuthType {
                // 更新 Service
                err = business.CreateHttpTriggerService(fcClient, trigger)
                if err != nil {
                    _ = logger.Error("handleUpdateTrigger: CreateHttpTriggerService error %s", err.Error())
                    handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
                    return
                }
            }
        } else {
            // 2. 否则需要将 KongPlugin、Service 和 Ingress 全部更新
            //    更新规则为先创建新的资源，创建成功后再删除原有的资源，
            //    防止创建新资源失败后导致原有资源也无法使用。
            //    注：这块逻辑和创建 HTTP 触发器的逻辑一样，但是错误信息不一样
            // 2.1. 校验同一个函数的同一个版本/别名只能有一个 HTTP 触发器
            exist, err := model.CheckHttpTriggerExist(trigger)
            if err != nil {
                _ = logger.Error("handleCreateTrigger CheckHttpTriggerExist error %v", err)
                handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
                return
            }
            if exist {
                handleInternalError(response, model.InternalServerError(model.TriggerError,
                    "更新触发器失败，同一函数的同一版本/别名只能创建一个 HTTP 触发器"))
                return
            }
            // 2.2. 创建新的 HTTP 触发器对应的 Service 和 KongPlugin
            err = business.CreateHttpTriggerKongPlugin(fcClient, trigger)
            if err != nil {
                _ = logger.Error("handleCreateTrigger CreateHttpTriggerKongPlugin error %v", err)
                handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
                return
            }
            err = business.CreateHttpTriggerService(fcClient, trigger)
            if err != nil {
                _ = logger.Error("handleCreateTrigger CreateHttpTriggerService error %v", err)
                handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
                return
            }
            // 2.3. 获取账号对应的唯一 Ingress default-<accountId>，并创建路由规则
            err = business.CreateHttpTriggerIngress(fcClient, trigger)
            if err != nil {
                _ = logger.Error("handleCreateTrigger CreateHttpTriggerIngress error %v", err)
                handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
                return
            }
            // 2.4 删除旧触发器对应的资源，这个地方暂且不做错误处理，即使没删掉也不影响再次创建。
            //     更稳妥的做法（精简逻辑，暂时不做）：确保至少把三种资源中的一种删掉，以确保旧触发器是不可用的。
            _ = business.DeleteHttpTriggerResources(fcClient, oldTriggerInfo)
        }
        break
    default:
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.type_update")))
        return
    }

    trigger, err = model.UpdateTrigger(trigger)
    if err != nil {
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.update")))
        return
    }
    _ = response.WriteHeaderAndEntity(http.StatusOK, trigger)
}

func (api *APIHandler) handleDeleteTrigger(request *restful.Request, response *restful.Response) {
    logger.Debug("handleDeleteTrigger start.")

    fcClient, err := GetFcClient(api)
    if err != nil {
        _ = logger.Error("handleDeleteTrigger get cmanagerconfig error %v", err)
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.delete")))
        return
    }
    from := request.QueryParameter("from")
    triggerId := request.PathParameter("triggerId")
    trigger, err := model.GetTriggerById(triggerId)
    if err != nil {
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.delete")))
        return
    }

    switch trigger.Type {
    case "timer":
        // 定时触发器
        namespace := ksvc.GetTriggerNs(trigger)
        triggerName := trigger.FuncName + "-" + trigger.Name
        if err = pingsource.DeletePingsource(fcClient, namespace, triggerName); err != nil {
            if !strings.Contains(err.Error(), "not found") {
                _ = logger.Error("handleDeleteTrigger DeletePingsource error %v", err)
                handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.delete")))
                return
            }
        }
    case "oss":
        // 对象存储触发器
        //调用oss删除接口
        ossN := &model.OssNotification{}
        _ = json.Unmarshal([]byte(trigger.Config), ossN)
        ossApiHost := model.Base.OssAdminHost
        if model.Base.OssUserHost != "" {
            ossApiHost = model.Base.OssUserHost
        }
        token := request.HeaderParameter("Authorization")
        err := deleteOssNotification(ossApiHost, token, ossN.BucketName, ossN.Id)
        if err != nil {
            // 删除失败时候不抛出错误
            _ = logger.Error("handleDeleteTrigger: Delete oss Notification error %v", err)
        }
    case "apig":
        // API 网关触发器
        if from == "apig" {
            break
        } else {
            apigC := &model.ApigConfig{}
            _ = json.Unmarshal([]byte(trigger.Config), apigC)
            token := request.HeaderParameter("Authorization")
            err = offlineApig(model.Base.ApigHost, token, apigC.Id, apigC.IsRelease)
            if err != nil {
                // 删除失败时候不抛出错误
                _ = logger.Error("handleDeleteTrigger: offlineApig error %v", err)
            }
        }
    case "http":
        // HTTP 触发器
        err := business.DeleteHttpTriggerResources(fcClient, trigger)
        if err != nil {
            _ = logger.Error("handleDeleteTrigger: delete http trigger error %s", err.Error())
            handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.delete")))
            return
        }
    }

    if err := model.DeleteTrigger(trigger.Id); err != nil {
        handleInternalError(response, model.InternalServerError(model.TriggerError, i18n.GetMessage(request.Request, "fcs.trigger.delete")))
        return
    }
}

func (api *APIHandler) handleCheckTriggerExist(request *restful.Request, response *restful.Response) {
    groupId := request.PathParameter("groupId")
    funcId := request.PathParameter("functionId")
    triggerName := request.QueryParameter("triggerName")
    user := currentUser(request)
    exist, err := model.CheckTriggerExist(user.Id, groupId, funcId, triggerName)
    if err != nil {
        _ = logger.Error("handleCheckGroupExist CheckGroupExist error %v", err)
    }
    _ = response.WriteHeaderAndEntity(http.StatusOK, map[string]interface{}{"exist": exist})
}

func assembleApigConfig(trigger *model.Trigger, apigC *model.ApigConfig) *model.ApigConfig {
    apigC.Name = strings.Replace(trigger.Name+"_"+trigger.FuncName+"_"+rand.String(5), "-", "_", -1)
    apigC.Style = "0"       //rest
    apigC.BackendType = "1" //fcs
    apigC.IsSupportedCors = "0"
    apigC.RequestPath = "/" + apigC.Name
    apigC.ReturnResultContentType = "0"
    apigC.FaultTolerant = "0"
    apigC.Params = []string{}
    apigC.FcsGroupId = trigger.GroupId
    apigC.FcsGroupName = trigger.GroupName
    apigC.FcsGroupDisplayName = trigger.GroupDisplayName
    apigC.FcsFuncId = trigger.FuncId
    apigC.FcsFuncName = trigger.FuncName
    apigC.FcsVersionId = trigger.TargetId
    apigC.FcsVersionName = trigger.TargetName
    if apigC.IsRelease == "1" {
        apigC.OnlineTriggerId = trigger.Id
    }
    if apigC.IsRelease == "2" {
        apigC.TestTriggerId = trigger.Id
    }
    apigC.FcsTargetType = trigger.TargetType

    return apigC
}

func createOssNotification(serviceHost, token string, ossN *model.OssNotification) error {
    logger.Debug("createOssNotification start")
    url := serviceHost + "oss/v1/buckets/" + ossN.BucketName + "/notification"
    logger.Debug("url: ", url)
    b, _ := json.Marshal(ossN)
    _, err := utils.HttpReq(url, token, http.MethodPost, bytes.NewReader(b), nil)
    if err != nil {
        return err
    }
    logger.Debug("createOssNotification end")
    return nil
}

func deleteOssNotification(serviceHost, token, bucket, notificationId string) error {
    logger.Debug("deleteOssNotification start")
    url := serviceHost + "oss/v1/buckets/" + bucket + "/notification/" + notificationId
    logger.Debug("url: ", url)
    _, err := utils.HttpReq(url, token, http.MethodDelete, nil, nil)
    if err != nil {
        return err
    }
    logger.Debug("deleteOssNotification end")
    return nil
}

func createApig(serviceHost, token string, apigC *model.ApigConfig) (*model.ApigConfig, error) {
    logger.Debug("createApig start")
    url := serviceHost + "apig/apps/v1/groups/" + apigC.GroupId + "/apis"
    logger.Debug("url: ", url)
    b, _ := json.Marshal(apigC)
    body, err := utils.HttpReq(url, token, "POST", bytes.NewReader(b), nil)
    if err != nil {
        return &model.ApigConfig{}, err
    }
    apigInfo := &model.ApigConfig{}
    _ = json.Unmarshal(body, apigInfo)
    logger.Debug("createApig apigInfo: ", apigInfo)
    return apigInfo, nil
}

func updateApig(serviceHost, token string, apigC *model.ApigConfig) (*model.ApigConfig, error) {
    logger.Debug("updateApig start")
    url := serviceHost + "apig/apps/v1/apis/" + apigC.Id
    logger.Debug("url: ", url)
    b, _ := json.Marshal(apigC)
    body, err := utils.HttpReq(url, token, "PATCH", bytes.NewReader(b), nil)
    if err != nil {
        return &model.ApigConfig{}, err
    }
    apigInfo := &model.ApigConfig{}
    _ = json.Unmarshal(body, apigInfo)
    logger.Debug("updateApig apigInfo: ", apigInfo)
    return apigInfo, nil
}

func deleteApig(serviceHost, token string, id string) error {
    logger.Debug("deleteApig start")
    url := serviceHost + "apig/apps/v1/apis/" + id
    logger.Debug("deleteApig url: ", url)
    _, err := utils.HttpReq(url, token, "DELETE", nil, nil)
    if err != nil {
        _ = logger.Error("deleteApig  err : ", err)
        return err
    }
    return nil
}

func publishApig(serviceHost, token, gid, id, pe string) error {
    logger.Debug("publishApig start: %v", id)
    m := map[string]string{
        "groupId":            gid,
        "id":                 id,
        "publishEnvironment": pe,
        "from":               "fcs",
    }
    url := serviceHost + "apig/apps/v1/apis/" + id + "/action/release"
    logger.Debug("publishApig url: ", url)
    b, _ := json.Marshal(m)
    _, err := utils.HttpReq(url, token, "POST", bytes.NewReader(b), nil)
    if err != nil {
        _ = logger.Error("publishApig  err : ", err)
        return err
    }
    return nil
}

func offlineApig(serviceHost, token, id, env string) error {
    logger.Debug("offlineApig start: %v", id)
    m := map[string]string{
        "offlineEnvironment": env,
    }
    url := serviceHost + "apig/apps/v1/apis/" + id + "/action/offline"
    logger.Debug("offlineApig url: ", url)
    b, _ := json.Marshal(m)
    _, err := utils.HttpReq(url, token, "POST", bytes.NewReader(b), nil)
    if err != nil {
        _ = logger.Error("offlineApig  err : ", err)
        return err
    }
    return nil
}

func getInvokeUrl(serviceHost, token string, apigC *model.ApigConfig) (string, error) {
    url := serviceHost + "apig/apps/v1/groups/" + apigC.GroupId
    body, err := utils.HttpReq(url, token, "GET", nil, nil)
    if err != nil {
        return "", err
    }
    g := map[string]string{}
    _ = json.Unmarshal(body, &g)
    if apigC.RequestProtocol == "1" {
        return "https://" + g["secondaryDomainName"] + "/" + apigC.Name, nil
    }
    if apigC.RequestProtocol == "0" {
        return "http://" + g["secondaryDomainName"] + "/" + apigC.Name, nil
    }
    return "https://" + g["secondaryDomainName"] + "/" + apigC.Name, nil
}

func getNewConfig(old, k, v string) string {
    m := map[string]string{}
    _ = json.Unmarshal([]byte(old), &m)
    m[k] = v
    nc, _ := json.Marshal(m)
    return string(nc)
}
